﻿using System;
using System.Collections.Generic;
using System.Linq;
using NetSurveillance.WebApp.DataServices.Models;
using ServiceStack.OrmLite;

namespace NetSurveillance.WebApp.DataServices.Implementations
{
    public class WhiteListService : BaseService<WhiteList>
    {
        public WhiteListService(string connStr, IOrmLiteDialectProvider provider = null)
            : base(connStr, provider)
        {
        }

        public ServiceResult SaveAll(IEnumerable<WhiteList> models, long taskId)
        {
            var whiteLists = models as IList<WhiteList> ?? models.ToList();
            using (var db = DbFactory.OpenDbConnection())
            {
                using (var trans = db.OpenTransaction())
                {
                    try
                    {
                        var modelsInDb = db.Select<WhiteList>(p => p.TaskId == taskId);
                        foreach (var whInDb in modelsInDb)
                        {
                            whInDb.StatusToken = CheckModelContains(whiteLists, whInDb) ? 1 : 0;
                            whInDb.LastModifiedTime = DateTime.Now;
                            db.Update(whInDb);
                        }
                        foreach (var whiteList in whiteLists.Where(p => !CheckModelContains(modelsInDb, p)))
                        {
                            db.Insert(whiteList);
                        }
                    }
                    catch (Exception ex)
                    {
                        //todo:log ex
                        trans.Rollback();
                        return new ServiceResult(false, ex.Message);
                    }
                    trans.Commit();
                }
            }
            return ServiceResult.SuccessResult;
        }

        public bool CheckModelContains(IEnumerable<WhiteList> whiteLists, WhiteList model)
        {
            switch (model.Type)
            {
                case "Domain":
                    return
                        whiteLists.Any(p => p.Type == "Domain" &&
                                            p.DomainName.ToLower() == model.DomainName.ToLower());
                case "Mac":
                    return
                        whiteLists.Any(p => p.Type == "Mac" &&
                                            p.Mac.ToLower() == model.Mac.ToLower());
                case "Port":
                    {
                        var wl = whiteLists.FirstOrDefault(p => p.Type == "Port" &&
                                                                (p.PortStart == model.PortStart ||
                                                                 (p.PortEnd.HasValue && p.PortEnd == model.PortEnd)));
                        if (wl != null)
                        {
                            model.PortStart = wl.PortStart;
                            model.PortEnd = wl.PortEnd;
                            return true;
                        }
                        return false;
                    }                    
                case "Ip":
                    {
                        var wl = whiteLists.FirstOrDefault(p => p.Type == "Ip" &&
                                                                (p.IpStart == model.IpStart ||
                                                                 (!string.IsNullOrWhiteSpace(p.IpEnd) &&
                                                                  p.IpEnd == model.IpEnd)));
                        if (wl != null)
                        {
                            model.IpStart = wl.IpStart;
                            model.IpEnd = wl.IpEnd;
                            return true;
                        }
                        return false;
                    }
            }
            return false;
        }

        private string GetSingleWhere(WhiteList whiteList)
        {
            string whereSql = " \"TaskId\"={0} and \"Type\"={1} ".Params(whiteList.TaskId, whiteList.Type);
            switch (whiteList.Type)
            {
                case "Domain":
                    return whereSql + " and \"DomainName\"={0}".Params(whiteList.DomainName);
                case "Mac":
                    return whereSql + " and \"Mac\"={0}".Params(whiteList.Mac);
                case "Port":
                    return whereSql + " and \"PortStart\"={0} ".Params(whiteList.PortStart) +
                           (whiteList.PortEnd.HasValue ? " and \"PortEnd\"={0}".Params(whiteList.PortEnd) : string.Empty);
                case "Ip":
                    return whereSql + " and \"IpStart\"={0}".Params(whiteList.IpStart) +
                           (!string.IsNullOrWhiteSpace(whiteList.IpEnd)
                                ? " and \"IpEnd\"={0}".Params(whiteList.IpEnd)
                                : string.Empty);
            }
            return whereSql;
        }

        public ServiceResult SaveWhiteListHost(long taskId, long[] hostIds)
        {
            using (var db = DbFactory.OpenDbConnection())
            {
                using (var trans = db.OpenTransaction())
                {
                    try
                    {
                        var wlHosts = db.Select<WhiteListHost>(p => p.TaskId == taskId);
                        //数据库中已有
                        foreach (var wlHost in wlHosts)
                        {
                            wlHost.StatusToken = hostIds.Contains(wlHost.HostId) ? 1 : 0;
                            wlHost.LastModifiedTime = DateTime.Now;
                            db.Save(wlHost);
                        }
                        //数据库中未有
                        bool isDbEmptry = !wlHosts.Any();
                        foreach (long hostId in hostIds.Where(p => isDbEmptry || wlHosts.All(ve => ve.HostId != p)))
                        {
                            var wlHost = new WhiteListHost { HostId = hostId, TaskId = taskId };
                            db.Save(wlHost);
                        }
                    }
                    catch (Exception ex)
                    {
                        //todo:记录ex问题
                        trans.Rollback();
                        return new ServiceResult { ExecutedSuccess = false, Message = ex.Message };
                    }
                    trans.Commit();
                }
                return ServiceResult.SuccessResult;
            }
        }
    }
}
